from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
from rest_framework.validators import ValidationError
from rest_framework.permissions import IsAuthenticated
from rest_framework.utils.serializer_helpers import ReturnList
from rest_framework.viewsets import ModelViewSet
from rest_framework import status
from rest_framework.response import Response
from rest_framework.generics import CreateAPIView
from apps.users.models import Permission, Role, RolePermission, User
from apps.users.serializers import (
    LoginSerializer,
    MyTokenRefreshSerializer,
    UserSerializers,
    PermissionSerializer,
    RoleSerializer,
    RolePermissionSerializer
)
from utils.base_view import BaseModelViewSet, BaseCreateModelViewSet
from utils.base import BasePageNumberPagination
from apps.users.filters import PermissionFilter, RoleFilter, UserFilter


class LoginView(TokenObtainPairView):
    serializer_class = LoginSerializer


class MyTokenRefreshView(TokenRefreshView):
    serializer_class = MyTokenRefreshSerializer


class UserViewSet(BaseModelViewSet):
    serializer_class = UserSerializers
    queryset = User.objects.all()
    permission_classes = [IsAuthenticated]
    pagination_class = BasePageNumberPagination
    filterset_class = UserFilter


class UserRegister(BaseCreateModelViewSet):
    serializer_class = UserSerializers
    queryset = User.objects.all()


class RolePermissionViewSet(BaseModelViewSet):
    queryset = RolePermission.objects.all()
    serializer_class = RolePermissionSerializer
    permission_classes = [IsAuthenticated]

    def _update_role_permission(self, role_permission, user_id):
        has_permission = role_permission['has_permission']
        has_read_permission = role_permission['has_read_permission']
        has_edit_permission = role_permission['has_edit_permission']
        has_add_permission = role_permission['has_add_permission']
        has_delete_permission = role_permission['has_delete_permission']
        role_id = self.kwargs.get('pk')
        permission_id = role_permission['id']
        role_permission_obj = RolePermission.objects.all().filter(role_id=role_id, permission_id=permission_id)

        if role_permission_obj:
            role_permission_obj = role_permission_obj[0]
            role_permission_obj.has_permission = has_permission
            role_permission_obj.has_read_permission = has_read_permission
            role_permission_obj.has_edit_permission = has_edit_permission
            role_permission_obj.has_add_permission = has_add_permission
            role_permission_obj.has_delete_permission = has_delete_permission
            role_permission_obj.create_by = user_id
            role_permission_obj.save()
        else:
            self._create_role_permission(has_permission, role_id, permission_id, has_read_permission,
                                         has_edit_permission, has_add_permission, has_delete_permission, user_id)

    @staticmethod
    def _create_role_permission(has_permission, role_id, permission_id, has_read_permission, has_edit_permission,
                                has_add_permission, has_delete_permission, user_id):
        RolePermission.objects.create(has_permission=has_permission, role_id=role_id, permission_id=permission_id,
                                      has_read_permission=has_read_permission, has_edit_permission=has_edit_permission,
                                      has_delete_permission=has_delete_permission, has_add_permission=has_add_permission,
                                      create_by=user_id, update_by=user_id)

    def create(self, request, *args, **kwargs):
        role_name = request.data['role_name']
        if Role.objects.all().filter(name=role_name):
            raise ValidationError({'msg': '角色名已存在'})
        role = Role.objects.create(name=role_name, create_by=self.request.user, update_by=self.request.user)
        for role_permission in request.data['items']:
            self._create_role_permission(role_permission['has_permission'],
                                         role.id, role_permission['id'],
                                         role_permission['has_read_permission'],
                                         role_permission['has_edit_permission'],
                                         role_permission['has_add_permission'],
                                         role_permission['has_delete_permission'],
                                         self.request.user)
            for children_role_permission in role_permission['children']:
                self._create_role_permission(children_role_permission['has_permission'], role.id,
                                             children_role_permission['id'],
                                             children_role_permission['has_read_permission'],
                                             children_role_permission['has_edit_permission'],
                                             children_role_permission['has_add_permission'],
                                             children_role_permission['has_delete_permission'],
                                             self.request.user)

        return Response({'data': role.id}, status=status.HTTP_201_CREATED)

    def update(self, request, *args, **kwargs):
        role_obj = Role.objects.all().get(id=self.kwargs.get('pk'))
        role_name = request.data['role_name']
        if Role.objects.all().filter(name=role_name) and role_obj.name != role_name:
            raise ValidationError({'msg': '角色名已存在11'})
        role_obj.name = role_name
        role_obj.update_by = self.request.user
        role_obj.save()
        for role_permission in request.data['items']:
            self._update_role_permission(role_permission, self.request.user)
            for children_role_permission in role_permission['children']:
                self._update_role_permission(children_role_permission, self.request.user)

        return Response({'data': role_obj.id}, status=status.HTTP_201_CREATED)


class RoleViewSet(BaseModelViewSet):
    queryset = Role.objects.all()
    serializer_class = RoleSerializer
    permission_classes = [IsAuthenticated]
    pagination_class = BasePageNumberPagination
    filterset_class = RoleFilter

    @staticmethod
    def _get_permissions(role_id):
        permissions = list(Permission.objects.all().filter(is_delete=False).values())
        permissions.sort(key=lambda x: x['level'])
        results = {}
        for permission_obj in permissions:
            role_permission_obj = RolePermission.objects.all().filter(role=role_id, permission=permission_obj['id'])
            if not role_permission_obj:
                permission_obj['has_permission'] = False
                permission_obj['has_read_permission'] = False
                permission_obj['has_edit_permission'] = False
                permission_obj['has_add_permission'] = False
                permission_obj['has_delete_permission'] = False
            else:
                role_permission_obj = role_permission_obj[0]
                permission_obj['role_permission_id'] = role_permission_obj.id
                permission_obj['has_permission'] = role_permission_obj.has_permission
                permission_obj['has_read_permission'] = role_permission_obj.has_read_permission
                permission_obj['has_edit_permission'] = role_permission_obj.has_edit_permission
                permission_obj['has_add_permission'] = role_permission_obj.has_add_permission
                permission_obj['has_delete_permission'] = role_permission_obj.has_delete_permission
            if permission_obj['level'] == 1:
                results[permission_obj['id']] = permission_obj
                results[permission_obj['id']]['children'] = []
            else:
                results[permission_obj['parent']]['children'].append(permission_obj)
        return results

    def retrieve(self, request, *args, **kwargs):
        role_id = self.kwargs.get('pk')
        all_permissions = self._get_permissions(role_id)
        response = super().retrieve(request, *args, **kwargs)
        response.data['role_permissions'] = all_permissions.values()
        return response


class PermissionView(BaseModelViewSet):
    queryset = Permission.objects.all()
    serializer_class = PermissionSerializer
    permission_classes = [IsAuthenticated]
    filterset_class = PermissionFilter

    def list(self, request, *args, **kwargs):
        response = super().list(request, *args, **kwargs)
        if request.query_params.get('back_list'):
            return response
        all_count = len(response.data)
        response.data.sort(key=lambda x: x['level'])
        results = {}
        for permission_obj in response.data:
            permission_obj['count'] = all_count
            permission_obj['has_permission'] = False
            permission_obj['has_read_permission'] = False
            permission_obj['has_edit_permission'] = False
            permission_obj['has_add_permission'] = False
            permission_obj['has_delete_permission'] = False
            if permission_obj['level'] == 1:
                results[permission_obj['id']] = permission_obj
                results[permission_obj['id']]['children'] = []
            else:
                results[permission_obj['parent']]['children'].append(permission_obj)
        response.data = results.values()
        return response






